package com.fulihui.wgj.consumer.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fulihui.common.util.CloneUtils;
import com.fulihui.common.util.JedisUtil;
import com.fulihui.common.util.TemplateDisabledUtil;
import com.fulihui.common.util.TemplateMsgCancelUtil;
import com.fulihui.open.shortlink.model.WgjSendLink;
import com.fulihui.weixinsdk.model.TemplateItem;
import com.fulihui.wgj.consumer.config.property.ShortLinkProperties;
import com.fulihui.wgj.consumer.result.BatchSendResult;
import com.fulihui.wgj.consumer.service.TemplateMsgService;
import com.fulihui.wgj.consumer.service.WxMsgService;
import com.fulihui.wgj.facade.dto.MsgUserDTO;
import com.fulihui.wgj.facade.dto.TemplateMsgDTO;
import com.fulihui.wgj.facade.msg.TemplateMsg;
import com.fulihui.wgj.facade.service.template.SendTemplateLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;

import static com.fulihui.common.constants.PlaceholderConstants.NICK_NAME;

/**
 * @author: LiuJie
 * @version: 2018/8/7 14:32
 * @description:
 */
@Service
@Slf4j
public class TemplateMsgServiceImpl implements TemplateMsgService {

    @Autowired
    private JedisUtil jedisUtil;
    @Autowired
    private WxMsgService wxMsgService;
    @Autowired
    private TemplateDisabledUtil templateDisabledUtil;
    @Autowired
    private ShortLinkProperties shortLinkProperties;
    @Autowired
    private TemplateMsgCancelUtil templateMsgCancelUtil;

    /**
     * 批量处理模板消息发送
     *
     * @param msg
     * @return
     */
    @Override
    public BatchSendResult batchHandle(TemplateMsg msg) {
        String appId = msg.getAppId();
        List<MsgUserDTO> users = msg.getUsers();

        String newsKey = msg.getNewsKey();
        Long recordId = msg.getRecordId();
        if (StringUtils.isBlank(appId)
                || StringUtils.isBlank(newsKey)
                || CollectionUtils.isEmpty(users)) {
            log.error("模板消息发送关键数据为空，msg={}", msg);
            return null;
        }

        String s = jedisUtil.get(newsKey);
        if (StringUtils.isBlank(s)) {
            log.error("模板消息发送，redis中数据模板为空，msg={}", msg);
            return null;
        }
        TemplateMsgDTO templateMsgDTO = JSON.parseObject(s, TemplateMsgDTO.class);

        // 非法模板不推送
        if (!templateDisabledUtil.checkTemplate(templateMsgDTO.getTemplateId())) {
            log.info("模板失效，不推送！{}", msg);
            return null;
        }
        // 取消发送则不发送
        if (!templateMsgCancelUtil.checkRecore(recordId.toString())) {
            log.info("模板消息该批次取消，不推送！{}", msg);
            return null;
        }

        BatchSendResult result = new BatchSendResult();
        for (MsgUserDTO user : users) {
            // 深度复制、保证模板纯洁性
            TemplateMsgDTO copy = CloneUtils.clone(templateMsgDTO);

            // 发送
            boolean sendStatus = send(appId, user, copy);

            // 记录成功失败-批次信息
            result.add(sendStatus);
        }
        return result;
    }

    /**
     * 发送逻辑，昵称替换、token 拼接等
     *
     * @param copy 模板的副本，会对该对象进行处理，不要用原版
     * @return 成功或失败
     */
    private boolean send(String appId, MsgUserDTO user, TemplateMsgDTO copy) {
        String openId = user.getOpenId();
        // 用户昵称替换
        if (StringUtils.isBlank(user.getNickName())) {
            user.setNickName("用户");
        }
        replaceNickname(copy.getData(), user.getNickName());

        // 短链拼接token
        //如果是短链接才拼接参数
        if (StringUtils.contains(copy.getTemplateUrl(), shortLinkProperties.getHost())) {
            String token = getToken(appId, copy.getTemplateId(), openId);
            if (copy.getTemplateUrl().contains("?")) {
                copy.setTemplateUrl(copy.getTemplateUrl() + "&uid=&token=" + token);
            } else {
                copy.setTemplateUrl(copy.getTemplateUrl() + "?uid=&token=" + token);
            }
        }

        return wxMsgService.sendTemplateMsg(appId, openId, copy);
    }

    private String getToken(String appId, String templateId, String openId) {
        // uid 废弃，短链未改造，只保留字段
        final String uId = "";
        long currentTimeMillis = System.currentTimeMillis();
        WgjSendLink wgjSendLink = new WgjSendLink();
        String secret = templateId + uId + currentTimeMillis + shortLinkProperties.getKey() + appId;
        secret = DigestUtils.md5DigestAsHex(secret.getBytes(StandardCharsets.UTF_8));
        wgjSendLink.setToken(secret);
        wgjSendLink.setStampTime(String.valueOf(currentTimeMillis));
        wgjSendLink.setTemplateid(templateId);
        wgjSendLink.setUid(uId);
        wgjSendLink.setOpenId(openId);
        wgjSendLink.setTemplatelogId(String.valueOf(templateId));
        wgjSendLink.setAppId(appId);

        //加密后的token
        String encode = "";
        String jsonString = JSONObject.toJSONString(wgjSendLink);
        try {
            encode = new String(Base64.getEncoder().encode(jsonString.getBytes("utf-8")));
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
            encode = "";
        }
        return encode;
    }

    private void replaceNickname(Map<String, TemplateItem> data, String nickname) {
        if (StringUtils.isNotBlank(nickname)) {
            data.forEach((k, v) -> {
                String content = v.getValue();
                if (content != null && content.indexOf(NICK_NAME) != -1) {
                    v.setValue(content.replaceAll(NICK_NAME, nickname));
                }
            });
        }
    }
}
